﻿using AutoMapper;
using BlogDemo.Common;
using BlogDemo.Data;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace BlogDemo.Application
{
    public class AppServiceBase<TDto, TEntity, TKey> : AppServiceBase<TDto, TEntity>, IAppService<TDto, TEntity, TKey>
     where TDto : IDto
     where TEntity : class, IEntity, IEntity<TKey>
     where TKey : IComparable<TKey>
    {
        public AppServiceBase(IRepositoryContext efRepositoryContext, IMapper mapper, IRepository<TEntity> repository) 
            : base(efRepositoryContext, mapper, repository)
        {
        }
    }
    //GenericService
    public class AppServiceBase<TDto, TEntity> : IAppService<TDto, TEntity>
        where TDto : IDto
        where TEntity : class, IEntity
    {

        private readonly IRepositoryContext _repositoryContext;
        private readonly IMapper _mapper;
        private readonly IRepository<TEntity> _repository;

        protected IRepositoryContext RepositoryContext { get { return _repositoryContext; } }

        protected   IRepository<TEntity> Repository { get { return _repository; } }
        protected IMapper Mapper { get { return _mapper; } }

        public AppServiceBase(IRepositoryContext efRepositoryContext, IMapper mapper, IRepository<TEntity> repository)
        {

            _mapper = mapper;
            this._repository = repository;
            this._repositoryContext = efRepositoryContext;
        }
        public virtual IEnumerable<TDto> GetAll()
        {
            var entities = _repository.Table;
            return _mapper.Map<IEnumerable<TDto>>(source: entities);
        }
        public virtual TDto Get(int id)
        {
            var entity = _repository.Find(id);
            return _mapper.Map<TDto>(source: entity);
        }

        public virtual IEnumerable<TDto> Get(Expression<Func<TEntity, bool>> predicate)
        {
            var entities = _repository.Find(predicate);
            return _mapper.Map<IEnumerable<TDto>>(source: entities);
        }

        public virtual int Add(TDto view)
        {
            var entity = _mapper.Map<TEntity>(source: view);
            _repository.Add(entity);
            RepositoryContext.Commit();
            return 1;
        }

        public virtual int Update(TDto view)
        {
            //int retval = _repository.Update(view.Id, _mapper.Map<TEntity>(source: view));
            //_unitOfWork.Commit();
            //return retval;
            return 1;
        }


        public virtual int Remove(int id)
        {
            //int retval = _repository.Remove(id);
            //_unitOfWork.Commit();
            //return retval;
            return 1;
        }

        public virtual async Task<IEnumerable<TDto>> GetAllAsync()
        {
            var entities = await _repository.QueryAsync();
            return _mapper.Map<IEnumerable<TDto>>(source: entities);
        }

        public virtual async Task<TDto> GetAsync(int id)
        {
            var entity = await _repository.FindAsync(id);
            return _mapper.Map<TDto>(source: entity);
        }
        public virtual async Task<IEnumerable<TDto>> GetAsync(Expression<Func<TEntity, bool>> predicate)
        {
            var items = await _repository.QueryAsync(predicate: predicate);
            return _mapper.Map<IEnumerable<TDto>>(source: items);
        }
        public virtual async Task<int> AddAsync(TDto view)
        {
            //var entity = _mapper.Map<TEntity>(source: view);
            //int id = await _repository.AddAsync(entity);
            //await _unitOfWork.SaveAsync();
            //return id;
            return 1;
        }

        public async Task<int> UpdateAsync(TDto view)
        {
            //int retval = await _repository.Update(view.Id, _mapper.Map<TEntity>(source: view));
            //await _unitOfWork.SaveAsync();
            //return retval;
            return 1;
        }

        public virtual async Task<int> RemoveAsync(int id)
        {
            //int retval = await _repository.Remove(id);
            //await _unitOfWork.SaveAsync();
            //return retval; 
            return 1;
        }
    }
}
